//*****************************************************************************
//
//									I2C.c
//
//*****************************************************************************
//
//
#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "I2C.h"
#include "printf.h"
#include "CPU.h"

//=============================================================================
//                                                                           
//=============================================================================
BYTE ReadI2C(BYTE addr, BYTE index)
{
	BYTE val, i;

	if ( addr == 0 ) return (ReadTW88(index));

	WriteTW88( 0xff, MCU_PAGE );
	i = ReadTW88( 0x20 ) & 4;	// is it cashe on?

	if ( i ) {
		I2CStartH();
		I2CWriteDataH(addr);
		I2CWriteDataH(index);
		I2CStartH();
		I2CWriteDataH(addr | 0x01);
		val = I2CReadDataH();
		I2CStopH();
	}
	else {
		I2CStartL();
		I2CWriteDataL(addr);
		I2CWriteDataL(index);
		I2CStartL();
		I2CWriteDataL(addr | 0x01);
		val = I2CReadDataL();
		I2CStopL();
	}
	return val;
}


void WriteI2C(BYTE addr, BYTE index, BYTE val)
{
	BYTE i;

	if ( addr == 0 ) {
		WriteTW88(index, val);
		return;
	}

	WriteTW88( 0xff, MCU_PAGE );
	i = ReadTW88( 0x20 ) & 4;	// is it cashe on?

	if ( i ) {
		I2CStartH();
		I2CWriteDataH(addr);
		I2CWriteDataH(index);
		I2CWriteDataH(val);
		I2CStopH();
	}
	else {
		I2CStartL();
		I2CWriteDataL(addr);
		I2CWriteDataL(index);
		I2CWriteDataL(val);
		I2CStopL();
	}
}

//=============================================================================
//                                                                           
//=============================================================================
/*
void dd(void)
{
	BYTE i;

	WriteTW88( 0xff, MCU_PAGE );
	if ( ReadTW88( 0x20 ) & 4 ) {		// is it cashe on?
	    i = ReadTW88( 0xff );
	}
}

void I2CStart()
{
	I2C_SDA = 1;	dd();
	I2C_SCL = 1;	dd();
	I2C_SDA = 0;	dd();
	I2C_SCL = 0;
}

void I2CStop()
{
	I2C_SDA = 0;	dd();
	I2C_SCL = 1;	dd();
	I2C_SDA = 1;
}

void I2CWriteData(BYTE value)
{
	I2C_SCL=0;	I2C_SDA=(value & 0x80)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x40)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x20)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x10)? 1:0;	I2C_SCL=1;	dd();

	I2C_SCL=0;	I2C_SDA=(value & 0x08)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x04)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x02)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x01)? 1:0;	I2C_SCL=1;	dd();


	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	//	I2Cdelay();
	I2C_SDA = 1;	//	I2Cdelay();

	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	//	I2Cdelay();
	dd();
	I2C_SCL = 0;
}

BYTE I2CReadData()
{
//	BYTE i;
	BYTE value;

	I2C_SDA = 1;
	I2C_SCL = 0;    dd();

//	
//	for(i=0; i<8; i++) {
//		I2C_SCL = 1;
//		value <<= 1;
//		//if(I2C_SDA) value |= 1;
//		value |= I2C_SDA;
//		dd();
//		I2C_SCL = 0;
//		dd();
//	}
//	
	I2C_SCL = 1;    dd();
	value = I2C_SDA;					  				// bit 7
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA;									// bit 6
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA; 									// bit 5
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA;									// bit 4
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA;  									// bit 3
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA; 									// bit 2
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA; 									// bit 1
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA; 									// bit 0

	I2C_SCL = 1;	// HHY 3.00
	dd();
	I2C_SCL = 0;

	return value;

}
*/
void I2CStartL()
{
	I2C_SDA = 1;
	I2C_SCL = 1;
	I2C_SDA = 0;
	I2C_SCL = 0;
}

void I2CStopL()
{
	I2C_SDA = 0;
	I2C_SCL = 1;
	I2C_SDA = 1;
}

void I2CWriteDataL(BYTE value)
{
	I2C_SCL=0;	I2C_SDA=(value & 0x80)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x40)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x20)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x10)? 1:0;	I2C_SCL=1;	I2C_SCL=1;

	I2C_SCL=0;	I2C_SDA=(value & 0x08)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x04)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x02)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x01)? 1:0;	I2C_SCL=1;	I2C_SCL=1;


	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	//	I2Cdelay();
	I2C_SDA = 1;	//	I2Cdelay();

	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	//	I2Cdelay();

	I2C_SCL = 0;
}

BYTE I2CReadDataL()
{
//	BYTE i;
	BYTE value;

	I2C_SDA = 1;
	I2C_SCL = 0;

	I2C_SCL = 1;
	value = I2C_SDA;					  				// bit 7
	I2C_SCL = 0;  	I2C_SCL = 1;
	value <<= 1;
	value |= I2C_SDA;									// bit 6
	I2C_SCL = 0;  	I2C_SCL = 1;
	value <<= 1;
	value |= I2C_SDA; 									// bit 5
	I2C_SCL = 0;  	I2C_SCL = 1;
	value <<= 1;
	value |= I2C_SDA;									// bit 4
	I2C_SCL = 0;  	I2C_SCL = 1;
	value <<= 1;
	value |= I2C_SDA;  									// bit 3
	I2C_SCL = 0;  	I2C_SCL = 1;
	value <<= 1;
	value |= I2C_SDA; 									// bit 2
	I2C_SCL = 0;  	I2C_SCL = 1;
	value <<= 1;
	value |= I2C_SDA; 									// bit 1
	I2C_SCL = 0;  	I2C_SCL = 1;
	value <<= 1;
	value |= I2C_SDA; 									// bit 0

	I2C_SCL = 1;	// HHY 3.00

	I2C_SCL = 0;

	return value;

}

void ddH(void)
{
	BYTE i;

	for ( i=0; i<5; i++ ) ;
}

void I2CStartH()
{
	I2C_SDA = 1;	ddH();
	I2C_SCL = 1;	ddH();
	I2C_SDA = 0;	ddH();
	I2C_SCL = 0;
}

void I2CStopH()
{
	I2C_SDA = 0;	ddH();
	I2C_SCL = 1;	ddH();
	I2C_SDA = 1;
}

void I2CWriteDataH(BYTE value)
{
	I2C_SCL=0;	I2C_SDA=(value & 0x80)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x40)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x20)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x10)? 1:0;	I2C_SCL=1;	ddH();

	I2C_SCL=0;	I2C_SDA=(value & 0x08)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x04)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x02)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x01)? 1:0;	I2C_SCL=1;	ddH();


	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	//	I2Cdelay();
	I2C_SDA = 1;	//	I2Cdelay();

	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	//	I2Cdelay();
	ddH();
	I2C_SCL = 0;
}

BYTE I2CReadDataH()
{
//	BYTE i;
	BYTE value;

	I2C_SDA = 1;
	I2C_SCL = 0;    ddH();

	I2C_SCL = 1;    ddH();
	value = I2C_SDA;					  				// bit 7
	I2C_SCL = 0;    ddH();  	I2C_SCL = 1;    ddH();
	value <<= 1;
	value |= I2C_SDA;									// bit 6
	I2C_SCL = 0;    ddH();  	I2C_SCL = 1;    ddH();
	value <<= 1;
	value |= I2C_SDA; 									// bit 5
	I2C_SCL = 0;    ddH();  	I2C_SCL = 1;    ddH();
	value <<= 1;
	value |= I2C_SDA;									// bit 4
	I2C_SCL = 0;    ddH();  	I2C_SCL = 1;    ddH();
	value <<= 1;
	value |= I2C_SDA;  									// bit 3
	I2C_SCL = 0;    ddH();  	I2C_SCL = 1;    ddH();
	value <<= 1;
	value |= I2C_SDA; 									// bit 2
	I2C_SCL = 0;    ddH();  	I2C_SCL = 1;    ddH();
	value <<= 1;
	value |= I2C_SDA; 									// bit 1
	I2C_SCL = 0;    ddH();  	I2C_SCL = 1;    ddH();
	value <<= 1;
	value |= I2C_SDA; 									// bit 0

	I2C_SCL = 1;	// HHY 3.00
	ddH();
	I2C_SCL = 0;

	return value;

}

//=============================================================================
//                                                                           
//=============================================================================
void I2CDeviceInitialize(BYTE *RegSet)
{
	int	cnt=0;
	BYTE addr, index, val;

	addr = *RegSet;
	#ifdef DEBUG_TW88
	Printf("\nI2C address : %02bx", addr);
	#endif
	cnt = *(RegSet+1);
	RegSet += 2;

	while ((RegSet[0] != 0xFF) || (RegSet[1] != 0xFF)) // 0xff, 0xff is end of data
	{
		if ((RegSet[0] == 0xFF) && (RegSet[1]== 0xFE))
		{
			RegSet += 2;
			addr = *RegSet;
			#ifdef DEBUG_TW88
			Printf("\nI2C address : %02bx", addr);
			#endif
			cnt = *(RegSet+1);
			RegSet += 2;
			continue;
		}
		
		index = *RegSet;
		val = *(RegSet+1);
		WriteI2C(addr, index, val);

		//delay(5);
		#ifdef DEBUG_TW88
		Printf("\n    addr=%02x  index=%02x   val=%02x", (WORD)addr, (WORD)index, (WORD)val );
		#endif
		
		RegSet+=2;
	}
	WriteTW88(0xff, 0x00);		// set page 0
}

/////////////////////////////////////////
// Set I2C SCL pin high/low.
//
// Arguments: bSet - high/low bit
/////////////////////////////////////////
void i2cSetSCL_Chk(bit bSet)
{
	BYTE ucDummy; // loop dummy

	i2cSetSCL(bSet); // set SCL pin
	if (bSet == _HIGH) // if set pin high
	{
		ucDummy = I2C_CHECK_PIN_DUMMY; // initialize dummy
		while ((i2cSCL_PIN_STATUS() == _LOW) && (ucDummy--)) ; // check SCL pull high
	}
}

/////////////////////////////////////////
// Set I2C SDA pin high/low
//
// Arguments: bSet - high/low bit
/////////////////////////////////////////
void i2cSetSDA_Chk(bit bSet)
{
	BYTE ucDummy; // loop dummy

	i2cSetSDA(bSet); // set SDA pin
	if (bSet == _HIGH) // if set pin high
	{
		ucDummy = I2C_CHECK_PIN_DUMMY; // initialize dummy
		while ((i2cSDA_PIN_STATUS() == _LOW) && (ucDummy--)) ; // check SDA pull high
	}
}

//////////////////////////////////////////////////////////////
// Delay 4us
//////////////////////////////////////////////////////////////
void i2c_Delay(void)
{
	BYTE i;

	for (i=0; i<5; i++)
		;	
}

//////////////////////////////////////////////////////
// I2C start signal.
// <comment>
//  SCL ________
//              \_________
//  SDA _____
//           \____________
//
// Return value: None
//////////////////////////////////////////////////////
BOOL i2c_Start(void)
{
	BOOL bStatus = TRUE; 

	i2cSetSDA_Chk(_HIGH);
	i2c_Delay();
	i2cSetSCL_Chk(_HIGH);
	i2c_Delay();

	if ((i2cSCL_PIN_STATUS() == _LOW) || (i2cSDA_PIN_STATUS() == _LOW))
	{
		bStatus = FALSE;
	}
	else
	{
		i2cSetSDA(_LOW);
		i2c_Delay();
		i2cSetSCL(_LOW);
	}

	return bStatus;
}

/////////////////////////////////////////
// I2C stop signal.
// <comment>
//              ____________
//  SCL _______/
//                 _________
//  SDA __________/
/////////////////////////////////////////
void i2c_Stop(void)
{
	i2cSetSCL(_LOW);
	i2c_Delay();
	i2cSetSDA(_LOW);
	i2c_Delay();
	i2cSetSCL(_HIGH);
	i2c_Delay();
	i2cSetSDA(_HIGH);
	i2c_Delay();
}

//////////////////////////////////////////////////////////////////////////
// I2C send byte to device.
//
// Arguments: ucVal - send byte
// Return value: I2C acknowledge bit
//               I2C_ACKNOWLEDGE/I2C_NON_ACKNOWLEDGE
//////////////////////////////////////////////////////////////////////////
BOOL i2c_SendByte(BYTE ucVal)
{
	BYTE ucMask = 0x80;
	BOOL bAck; // acknowledge bit

	while (ucMask)
	{
		if (ucVal & ucMask)
			i2cSetSDA_Chk(_HIGH);
		else
			i2cSetSDA_Chk(_LOW);
		i2c_Delay();
		i2cSetSCL_Chk(_HIGH); // clock
		i2c_Delay();
		i2cSetSCL(_LOW);
		i2c_Delay();

		ucMask >>= 1; // next
	}

	// recieve acknowledge
	i2cSetSDA(_HIGH);
	i2c_Delay();
	i2cSetSCL(_HIGH);
	i2c_Delay();
	bAck = i2cSDA_PIN_STATUS(); // recieve acknowlege
	i2cSetSCL(_LOW);

	return (bAck);
}

//////////////////////////////////////////////////////////////////////////
// I2C receive byte from device.
//
// Return value: receive byte
//////////////////////////////////////////////////////////////////////////
BYTE i2c_ReceiveByte(BOOL bFrist, BOOL bAck)
{
	BYTE ucReceive = 0;
	BYTE ucMask = 0x80;

	while (ucMask)
	{
		if (bFrist==FALSE)
		{
			i2cSetSDA(_HIGH);
			i2cSetSCL(_HIGH);
		}
		else
		{
			bFrist=FALSE;
		}
		i2c_Delay();

		if (i2cSDA_PIN_STATUS() == _HIGH)
			ucReceive |= ucMask;

		i2cSetSCL(_LOW);
		i2c_Delay();

		ucMask >>= 1;
	}

	if (bAck) // acknowledge
		i2cSetSDA_Chk(I2C_ACKNOWLEDGE);
	else // non-acknowledge
		i2cSetSDA_Chk(I2C_NON_ACKNOWLEDGE);

	i2c_Delay();
	i2cSetSCL(_HIGH);
	i2c_Delay();
	i2cSetSCL(_LOW);

	return ucReceive;
}

//////////////////////////////////////////////////////////////////////////
// I2C access start.
//
// Arguments: ucSlaveAdr - slave address
//            trans_t - I2C_TRANS_WRITE/I2C_TRANS_READ
//////////////////////////////////////////////////////////////////////////
BOOL i2c_AccessStart(BYTE ucSlaveAdr, I2C_Direction trans_t)
{
	BYTE ucDummy; // loop dummy

	if (trans_t == I2C_READ) // check i2c read or write
		ucSlaveAdr = I2C_DEVICE_ADR_READ(ucSlaveAdr); // read
	else
		ucSlaveAdr = I2C_DEVICE_ADR_WRITE(ucSlaveAdr); // write

	ucDummy = I2C_ACCESS_DUMMY_TIME;
	while (ucDummy --)
	{    
		i2c_Delay();
		if (i2c_Start() == FALSE)
			continue;

		if (i2c_SendByte(ucSlaveAdr) == I2C_ACKNOWLEDGE) // check acknowledge
			return TRUE;

///		Printf("ucSlaveAdr====%x", ucSlaveAdr);
		i2c_Stop();
		
		delay(1);
	}

	return FALSE;
}

/////////////////////////////////////////////////////////////////
// I2C read bytes from device.
//
// Arguments: ucSlaveAdr - slave address
//            pBuf - pointer of buffer
//            ucBufLen - length of buffer
/////////////////////////////////////////////////////////////////
void MDrv_SW_IIC_ReadBytes(BYTE ucSlaveAdr, BYTE *pBuf, BYTE ucBufLen)
{
	BYTE ucDummy; // loop dummy
	BYTE byLen = ucBufLen;

	ucDummy = I2C_ACCESS_DUMMY_TIME;
	while (ucDummy --)
	{
		if (i2c_AccessStart(ucSlaveAdr, I2C_READ) == FALSE)
			continue;
		
		i2cSetSDA(_HIGH);
		i2cSetSCL(_HIGH);
		
		while (i2cSCL_PIN_STATUS() == _LOW)
		{
			i2c_Delay();
			i2c_Delay();
			i2c_Delay();
			i2c_Delay();
			i2c_Delay();
		}
		
		while (byLen --) // loop to burst read
		{
			*pBuf = i2c_ReceiveByte(byLen == (ucBufLen-1) ? TRUE : FALSE, byLen); // receive byte

			pBuf ++; // next byte pointer
		}

		break;
	}

	i2c_Stop();
}

